﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Pg.BioMedics.SDR.Entities;
using Pg.BioMedics.SDR.Entities.Codes;

namespace Pg.BioMedics.SDR.ServiceAgents
{
    /// <summary>
    /// Provides entry points for logic provided by ASR component via SOAP 
    /// interface. This agent 
    /// </summary>
    public class ASRAgent : BaseServiceAgent
    {
        #region Constants

        private const string TaskTypeCode = "mpeg7";
        private const string TaskPriorityCode = "normal";
        private const string TaskStateSuccess = "success";
        private const string TaskStateFailed = "failed";

        #endregion

        #region Constructors

        /// <summary>
        /// Creates instance of ASRAgent. This constructor is intended 
        /// to be used for internal purposes only
        /// <param name="endpointName">Endpoint name</param>
        /// <param name="securityStrategy">Security strategy</param>
        /// </summary>
        internal ASRAgent(string endpointName, ISecurityStrategy securityStrategy) 
            : base(endpointName, securityStrategy) { }

        #endregion

        #region Methods

        /// <summary>
        /// Enqueues a new ASR task in external ASR service.
        /// </summary>
        /// <param name="name">Media file name</param>
        /// <param name="media">Media file content</param>
        /// <returns>ASR task unique id</returns>
        public Guid EnqueueTask(string name, byte[] media)
        {
            try
            {
                using (ASRWebService.ASRServiceClient client = new ASRWebService.ASRServiceClient(EndpointName))
                {
                    SecurityStrategy.ApplyCredentials(client.ClientCredentials);

                    ASRWebService.Task task = client.EnqueueTask(name, TaskTypeCode, TaskPriorityCode, media);
                    return new Guid(task.UniqueId);
                }
            }
            catch (Exception ex)
            {
                throw new ServiceAgentException("Could not enqueue task {0}", ex, name);
            }
        }

        /// <summary>
        /// Gets list of finished ASR tasks. 
        /// This tasks have assigned MPEG-7 descriptor
        /// extracted from supplied multimedia content.
        /// </summary>
        /// <returns>List of finished tasks unique identifiers</returns>
        public IList<Guid> GetFinishedTasks()
        {
            try
            {
                using (ASRWebService.ASRServiceClient client = new ASRWebService.ASRServiceClient(EndpointName))
                {
                    SecurityStrategy.ApplyCredentials(client.ClientCredentials);

                    return (from task in client.GetResultingTasks()
                            where task.StateCode == TaskStateSuccess
                            select new Guid(task.UniqueId)).ToList();
                }
            }
            catch (Exception ex)
            {
                throw new ServiceAgentException("Could not get finished tasks list", ex);
            }
        }

        /// <summary>
        /// Gets list of failed tasks 
        /// </summary>
        /// <returns>List of field ASR tasks</returns>
        public IList<Guid> GetFailedTasks()
        {
            try
            {
                using (ASRWebService.ASRServiceClient client = new ASRWebService.ASRServiceClient(EndpointName))
                {
                    SecurityStrategy.ApplyCredentials(client.ClientCredentials);

                    return (from task in client.GetResultingTasks()
                            where task.StateCode == TaskStateFailed
                            select new Guid(task.UniqueId)).ToList();
                }
            }
            catch (Exception ex)
            {
                throw new ServiceAgentException("Could not get finished tasks list", ex);
            }
        }

        /// <summary>
        /// Gets ASR task result content. If task has succeeded 
        /// MPEG-7 descriptor content will be downloaded. Otherwise 
        /// an error message.
        /// </summary>
        /// <param name="asrTaskUniqueId">ASR task unique identifier</param>
        /// <returns>MEPG-7 descriptor or error message</returns>
        public string GetResult(Guid asrTaskUniqueId)
        {
            try
            {
                using (ASRWebService.ASRServiceClient client = new ASRWebService.ASRServiceClient(EndpointName))
                {
                    SecurityStrategy.ApplyCredentials(client.ClientCredentials);

                    ASRWebService.Task task = client.GetTask(asrTaskUniqueId.ToString());
                    ASRWebService.Result result = client.GetResults(task).FirstOrDefault();
                    return (result != null ? result.Content : null);
                }
            }
            catch (Exception ex)
            {
                throw new ServiceAgentException("Could not get result for task {0}", ex, asrTaskUniqueId);
            }
        }

        /// <summary>
        /// Disposes task with given unique task id. This method calls
        /// finishTask method from ASR web service
        /// </summary>
        /// <param name="asrTaskUniqueId">ASR task unique id</param>
        public void DisposeTask(Guid asrTaskUniqueId)
        {
            try
            {
                using (ASRWebService.ASRServiceClient client = new ASRWebService.ASRServiceClient(EndpointName))
                {
                    SecurityStrategy.ApplyCredentials(client.ClientCredentials);

                    ASRWebService.Task task = client.GetTask(asrTaskUniqueId.ToString());
                    client.FinishTask(task);
                }
            }
            catch (Exception ex)
            {
                throw new ServiceAgentException("Could not dispose task {0}", ex, asrTaskUniqueId);
            }
        }

        #endregion
    }
}
